#include "login.h"
#include "flight.h"
#include "list.h"

int main(int argc, char const *argv[])
{
    // flag_1最外层循环条件：控制用户登陆循环；
    // flag_2内层循环条件：控制用户操作循环；
    // flag_3用户操作选项判断：用于接收用户的操作
    int flag_1 = 1, flag_2 = 1;
    char flag_3 = 0;

    // 存储用户身份和航票信息
    UserData user = {0};

    // 创建航班和用户数据链表，并从文件读取数据初始化
    FlightNode *flight_head = flightHeadNode();
    UserNode *user_head = userHeadNode();
    readFileData(&user_head, &flight_head);
    // 用户登录循环
    while (flag_1)
    {
        system("clear");
        printf("--------------------欢迎使用航班管理系统！--------------------\n");
        // 用户登陆判断，错误三次强制退出系统
        if (!loginOperation(user_head, &user))
        {
            return 0;
        }
        system("clear");
        flag_1 = user.id;
        if (flag_1 == 1)
        {
            flag_2 = 1;
            // 管理员操作循环
            while (flag_2)
            {
                system("clear");
                flag_3 = 0;
                printf("+----------------------------------------------------------+\n"
                       "|                欢迎使用管理员界面！                      |\n"
                       "|                                                          |\n"
                       "|   (1)增加航班信息    (2)浏览航班信息      (3)查询航班信息|\n"
                       "|                                                          |\n"
                       "|                                                          |\n"
                       "|   (4)修改航班信息    (5)删除航班信息      (6)排序航班信息|\n"
                       "|                                                          |\n"
                       "|                                                          |\n"
                       "|   (7)购票 (8)退票    (9)返回登陆         (0)退出系统     |\n"
                       "|                                                          |\n"
                       "+----------------------------------------------------------+\n");
                printf("请输入您要操作的选项：");
                scanf(" %c", &flag_3);
                // 管理员操作选项 switch语句
                switch (flag_3)
                {
                case '1':
                    system("clear");
                    addFlightInformation(flight_head);
                    break;
                case '2':
                    system("clear");
                    showFlightNode(flight_head);
                    break;
                case '3':
                    system("clear");
                    searchFlightInformation(flight_head);
                    break;
                case '4':
                    system("clear");
                    modifyFlightInformation(flight_head);
                    break;
                case '5':
                    system("clear");
                    deleteFlightInformation(flight_head);
                    break;
                case '6':
                    system("clear");
                    sortFlightInformation(flight_head);
                    break;

                case '7':
                    system("clear");
                    buyTicket(flight_head, &user);
                    updateUserNode(user_head, &user);
                    break;
                case '8':
                    system("clear");
                    refundTicket(flight_head, &user);
                    updateUserNode(user_head, &user);
                    break;
                case '9':
                    flag_2 = 0;
                    break;
                case '0':
                    writeFileData(user_head, flight_head);
                    removeUserList(user_head);
                    free(user_head);
                    user_head = NULL;
                    removeFlightList(flight_head);
                    free(flight_head);
                    flight_head = NULL;
                    return 0;
                default:
                    printf("输入错误!\n");
                }
                // 管理员操作后的选项选择
                printf("(1)返回上一级\t(2)重新登陆\n");
                scanf(" %c", &flag_3);
                if (flag_3 == '1')
                {
                    continue;
                }
                else if (flag_3 == '2')
                {
                    flag_2 = 0;
                }
            }
        }
        // 用户操作循环
        else if (flag_1 == 2)
        {
            flag_2 = 1;
            while (flag_2)
            {
                flag_3 = 0;
                system("clear");
                printf("+---------------------------------------------+\n"
                       "|                  航班管理系统               |\n"
                       "|                                             |\n"
                       "|                  1.购票                     |\n"
                       "|                  2.退票                     |\n"
                       "|                  3.退回登陆                 |\n"
                       "|                  4.退出系统                 |\n"
                       "|                                             |\n"
                       "+---------------------------------------------+\n");
                printf("请输入你要操作的选项：");
                scanf(" %c", &flag_3);
                // 用户操作选项判断
                if (flag_3 == '1')
                {
                    system("clear");
                    buyTicket(flight_head, &user);
                    updateUserNode(user_head, &user);
                }
                else if (flag_3 == '2')
                {
                    system("clear");
                    refundTicket(flight_head, &user);
                    updateUserNode(user_head, &user);
                }
                else if (flag_3 == '3')
                {
                    flag_2 = 0;
                }
                else if (flag_3 == '4')
                {
                    writeFileData(user_head, flight_head);
                    removeUserList(user_head);
                    free(user_head);
                    user_head = NULL;
                    removeFlightList(flight_head);
                    free(flight_head);
                    flight_head = NULL;
                    return 0;
                }
                else
                {
                    printf("输入错误\n");
                }
                // 管理员操作后的选项选择
                printf("(1)返回上一级\t(2)重新登陆\n");
                scanf(" %c", &flag_3);
                if (flag_3 == '1')
                {
                    continue;
                }
                else if (flag_3 == '2')
                {
                    flag_2 = 0;
                }
            }
        }
    }
    // 退出前的数据保存和内存释放
    writeFileData(user_head, flight_head);
    removeUserList(user_head);
    free(user_head);
    user_head = NULL;
    removeFlightList(flight_head);
    free(flight_head);
    flight_head = NULL;
    return 0;
}
// 单用户登录功能：登录界面，用户名，密码。（管理员账户，单链表,所有功能单用户即可。）用户信息可用文件存储。    已检验
bool loginOperation(UserNode *head, UserData *user)
{
    if (!head->next)
    {
        printf("登录失败：链表为空。\n");
        return false;
    }
    // 用于存储用户输入的用户名和密码
    UserData input_user = {0};
    // 登录尝试次数
    int login_attempts = 3;
    while (login_attempts)
    {
        UserNode *p = head->next;
        printf("请输入账号(回车结束输入):");
        scanf(" %s", input_user.name);
        // fgets(input_user.name,sizeof(input_user.name),stdin);
        // input_user.name[strcspn(input_user.name, "\n")] = 0;
        printf("请输入密码(回车结束输入):");
        scanf(" %s", input_user.pws);
        // 遍历链表，比对输入的用户名和密码与链表中存储的数据是否匹配
        for (int i = 0; i < head->len; i++)
        {
            if (!strcmp(input_user.pws, p->data.pws) && !strcmp(input_user.name, p->data.name))
            {
                printf("登陆成功\n");
                *user = p->data;
                return true;
            }

            p = p->next;
        }
        // 登录尝试失败，减少剩余尝试次数并提示
        if (login_attempts > 0)
        {
            printf("密码错误! 还有 %d 次机会\n", --login_attempts);
        }
    }
    printf("密码错误! 尝试次数用完，登录失败\n");
    return false;
}
// 读取文件数据功能：该功能实现了读取txt文本内航班信息和用户信息，并将其写入到链表中,自动过滤之前和十天以后的航班信息           已检验
void readFileData(UserNode **user_head, FlightNode **flight_head)
{
    // 打开航班信息文件和用户信息文件
    FILE *ft = fopen("flight.txt", "r");
    FILE *fu = fopen("user.txt", "r");
    // 航班和用户数据临时存储结构体
    FlightData f_data = {0};
    UserData u_data = {0};
    if (ft == NULL)
    {
        printf("航班信息读取失败");
        return;
    }
    // 循环读取航班信息文件每行数据
    while (!feof(ft))
    {
        fscanf(ft, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\n",
               &f_data.id, f_data.flight_num, f_data.flight_type, f_data.start_city,
               f_data.start_time, f_data.arrive_city, f_data.arrive_time,
               &f_data.value, &f_data.max_num, &f_data.left_num);
        // 过滤掉之前和十天以后的航班信息
        if (difftime(time(NULL), convertTimeType(f_data.start_time)) < 0 || difftime(time(NULL), convertTimeType(f_data.start_time)) > 864000)
        {
            continue;
        }
        // 将符合条件的航班信息添加到航班链表
        addFlightNode(*flight_head, &f_data);
    }
    // 关闭航班信息文件
    fclose(ft);
    ft = NULL;

    if (fu == NULL)
    {
        printf("用户信息读取失败");
        return;
    }
    // }
    while (!feof(fu))
    {
        fscanf(fu, "%d\t%s\t%s\t%s\t%d\n",
               &u_data.id, u_data.name, u_data.pws, u_data.IDcard, &u_data.ticket_num);
        for (int i = 0; i < u_data.ticket_num; i++)
        {
            fscanf(fu, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\n",
                   &u_data.ticket[i].id, u_data.ticket[i].flight_num, u_data.ticket[i].flight_type, u_data.ticket[i].start_city,
                   u_data.ticket[i].start_time, u_data.ticket[i].arrive_city, u_data.ticket[i].arrive_time,
                   &u_data.ticket[i].value, &u_data.ticket[i].max_num, &u_data.ticket[i].left_num);
        }
        addUserNode(*user_head, &u_data);
    }
    fclose(fu);
    fu = NULL;
}
// 保存数据功能：该功能实现了将链表内航班信息写入到txt文本内。          已检验
void writeFileData(UserNode *user_head, FlightNode *flight_head)
{
    // 尝试打开航班信息文件和用户信息文件
    FILE *ft = fopen("flight.txt", "w+");
    FILE *fu = fopen("user.txt", "w+");
    // 遍历链表，写入航班信息
    FlightNode *f = flight_head->next;
    UserNode *u = user_head->next;
    if (ft == NULL)
    {
        printf("航班信息读取失败");
        return;
    }
    while (f != flight_head)
    {
        fprintf(ft, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\n",
                f->data.id, f->data.flight_num, f->data.flight_type, f->data.start_city,
                f->data.start_time, f->data.arrive_city, f->data.arrive_time,
                f->data.value, f->data.max_num, f->data.left_num);
        f = f->next;
    }
    // 关闭航班信息文件
    fclose(ft);
    ft = NULL;

    if (fu == NULL)
    {
        printf("用户信息读取失败");
        return;
    }
    while (u)
    {
        fprintf(fu, "%d\t%s\t%s\t%s\t%d\n",
                u->data.id, u->data.name, u->data.pws, u->data.IDcard, u->data.ticket_num);

        for (int i = 0; i < u->data.ticket_num; i++)
        {
            fprintf(fu, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\n",
                    u->data.ticket[i].id, u->data.ticket[i].flight_num, u->data.ticket[i].flight_type, u->data.ticket[i].start_city,
                    u->data.ticket[i].start_time, u->data.ticket[i].arrive_city, u->data.ticket[i].arrive_time,
                    u->data.ticket[i].value, u->data.ticket[i].max_num, u->data.ticket[i].left_num);
        }
        u = u->next;
    }
    fclose(fu);
    fu = NULL;
}

// 用户结构体节点信息更新函数：主要用于实时更新用户票据信息
void updateUserNode(UserNode *head, UserData *user)
{
    // 从头节点的下一个节点开始遍历用户列表
    UserNode *temp = head->next;

    // 遍历整个用户列表
    while (temp != NULL)
    {
        if (temp->data.name == NULL || temp->data.pws == NULL || user->name == NULL || user->pws == NULL)
        {
            // 错误处理或跳过此节点
            temp = temp->next;
            continue;
        }
        int i;
        for (i = 0; i < temp->data.ticket_num;)
        {
            if (difftime(time(NULL), convertTimeType(temp->data.ticket[i].start_time)) < 0)
            {
                for (int j = i; j < temp->data.ticket_num - 1; j++)
                {
                    temp->data.ticket[j] = temp->data.ticket[j + 1];
                }
                temp->data.ticket_num--;
            }
            else
            {
                i++;
            }
        }
        // 比较当前节点数据中的姓名和密码是否与目标用户匹配
        if (!strcmp(temp->data.name, user->name) && !strcmp(temp->data.pws, user->pws))
        {
            // 如果匹配，则更新该节点的数据为新的用户数据
            temp->data = *user;
            break;
        }
        temp = temp->next;
    }
}